home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 039a / dflat8.zip / MESSAGE.C < prev    next >
Text File  |  1991-09-30  |  17KB  |  538 lines

  1. /* --------- message.c ---------- */
  2.  
  3. #include "dflat.h"
  4.  
  5. static int px = -1, py = -1;
  6. static int pmx = -1, pmy = -1;
  7. static int mx, my;
  8.  
  9. static int CriticalError;
  10.  
  11. /* ---------- event queue ---------- */
  12. static struct events    {
  13.     MESSAGE event;
  14.     int mx;
  15.     int my;
  16. } EventQueue[MAXMESSAGES];
  17.  
  18. /* ---------- message queue --------- */
  19. static struct msgs {
  20.     WINDOW wnd;
  21.     MESSAGE msg;
  22.     PARAM p1;
  23.     PARAM p2;
  24. } MsgQueue[MAXMESSAGES];
  25.  
  26. static int EventQueueOnCtr;
  27. static int EventQueueOffCtr;
  28. static int EventQueueCtr;
  29.  
  30. static int MsgQueueOnCtr;
  31. static int MsgQueueOffCtr;
  32. static int MsgQueueCtr;
  33.  
  34. static int lagdelay = FIRSTDELAY;
  35.  
  36. static void (interrupt far *oldtimer)(void);
  37. static void (interrupt far *oldkeyboard)(void);
  38.  
  39. static int keyportvalue;    /* for watching for key release */
  40.  
  41. WINDOW CaptureMouse;
  42. WINDOW CaptureKeyboard;
  43. static int NoChildCaptureMouse;
  44. static int NoChildCaptureKeyboard;
  45.  
  46. static int doubletimer = -1;
  47. static int delaytimer  = -1;
  48. static int clocktimer  = -1;
  49.  
  50. static WINDOW Cwnd;
  51.  
  52. static void interrupt far newkeyboard(void)
  53. {
  54.     keyportvalue = inp(KEYBOARDPORT);
  55.     oldkeyboard();
  56. }
  57.  
  58. /* ------- timer interrupt service routine ------- */
  59. static void interrupt far newtimer(void)
  60. {
  61.     if (timer_running(doubletimer))
  62.         countdown(doubletimer);
  63.     if (timer_running(delaytimer))
  64.         countdown(delaytimer);
  65.     if (timer_running(clocktimer))
  66.         countdown(clocktimer);
  67.     oldtimer();
  68. }
  69.  
  70. static char ermsg[] = "Error accessing drive x";
  71.  
  72. /* -------- test for critical errors --------- */
  73. int TestCriticalError(void)
  74. {
  75.     int rtn = 0;
  76.     if (CriticalError)    {
  77.         rtn = 1;
  78.         CriticalError = FALSE;
  79.         if (TestErrorMessage(ermsg) == FALSE)
  80.             rtn = 2;
  81.     }
  82.     return rtn;
  83. }
  84.  
  85. /* ------ critical error interrupt service routine ------ */
  86. static void interrupt far newcrit(IREGS ir)
  87. {
  88.     if (!(ir.ax & 0x8000))     {
  89.         ermsg[sizeof(ermsg) - 2] = (ir.ax & 0xff) + 'A';
  90.         CriticalError = TRUE;
  91.     }
  92.     ir.ax = 0;
  93. }
  94.  
  95. /* ------------ initialize the message system --------- */
  96. void init_messages(void)
  97. {
  98.     initvideo();
  99.     resetmouse();
  100.     set_mousetravel(0, SCREENWIDTH-1, 0, SCREENHEIGHT-1);
  101.     savecursor();
  102.     hidecursor();
  103.     px = py = -1;
  104.     pmx = pmy = -1;
  105.     mx = my = 0;
  106.     CaptureMouse = CaptureKeyboard = NULL;
  107.     NoChildCaptureMouse = FALSE;
  108.     NoChildCaptureKeyboard = FALSE;
  109.     MsgQueueOnCtr = MsgQueueOffCtr = MsgQueueCtr = 0;
  110.     EventQueueOnCtr = EventQueueOffCtr = EventQueueCtr = 0;
  111.     if (oldtimer == NULL)    {
  112.         oldtimer = getvect(TIMER);
  113.         setvect(TIMER, newtimer);
  114.     }
  115.     if (oldkeyboard == NULL)    {
  116.         oldkeyboard = getvect(KEYBOARDVECT);
  117.         setvect(KEYBOARDVECT, newkeyboard);
  118.     }
  119.     setvect(CRIT, newcrit);
  120.     PostMessage(NULL,START,0,0);
  121.     lagdelay = FIRSTDELAY;
  122. }
  123.  
  124. /* ----- post an event and parameters to event queue ---- */
  125. static void PostEvent(MESSAGE event, int p1, int p2)
  126. {
  127.     if (EventQueueCtr != MAXMESSAGES)    {
  128.         EventQueue[EventQueueOnCtr].event = event;
  129.         EventQueue[EventQueueOnCtr].mx = p1;
  130.         EventQueue[EventQueueOnCtr].my = p2;
  131.         if (++EventQueueOnCtr == MAXMESSAGES)
  132.             EventQueueOnCtr = 0;
  133.         EventQueueCtr++;
  134.     }
  135. }
  136.  
  137. /* ------ collect mouse, clock, and keyboard events ----- */
  138. static void near collect_events(void)
  139. {
  140.     static int ShiftKeys = 0;
  141.     int sk;
  142.     struct tm *now;
  143.     static int flipflop = FALSE;
  144.     static char timestr[9];
  145.     int hr;
  146.  
  147.     /* -------- test for a clock event (one/second) ------- */
  148.     if (timed_out(clocktimer))    {
  149.         /* ----- get the current time ----- */
  150.         time_t t = time(NULL);
  151.         now = localtime(&t);
  152.         hr = now->tm_hour > 12 ?
  153.              now->tm_hour - 12 :
  154.              now->tm_hour;
  155.         if (hr == 0)
  156.             hr = 12;
  157.         sprintf(timestr, "%2d:%02d", hr, now->tm_min);
  158.         strcpy(timestr+5, now->tm_hour > 11 ? "pm " : "am ");
  159.         /* ------- blink the : at one-second intervals ----- */
  160.         if (flipflop)
  161.             *(timestr+2) = ' ';
  162.         flipflop ^= TRUE;
  163.         /* -------- reset the timer -------- */
  164.         set_timer(clocktimer, 1);
  165.         /* -------- post the clock event -------- */
  166.         PostEvent(CLOCKTICK, FP_SEG(timestr), FP_OFF(timestr));
  167.     }
  168.  
  169.     /* --------- keyboard events ---------- */
  170.     if ((sk = getshift()) != ShiftKeys)    {
  171.         ShiftKeys = sk;
  172.         /* ---- the shift status changed ---- */
  173.         PostEvent(SHIFT_CHANGED, sk, 0);
  174.     }
  175.  
  176.     /* ---- build keyboard events for key combinations that
  177.         BIOS doesn't report --------- */
  178.     if (sk & ALTKEY)
  179.         if (inp(0x60) == 14)    {
  180.             waitforkeyboard();
  181.             PostEvent(KEYBOARD, ALT_BS, sk);
  182.         }
  183.     if (sk & CTRLKEY)
  184.         if (inp(0x60) == 82)    {
  185.             while (!(inp(0x60) & 0x80))
  186.             waitforkeyboard();
  187.             PostEvent(KEYBOARD, CTRL_INS, sk);
  188.         }
  189.  
  190.     /* ----------- test for keystroke ------- */
  191.     if (keyhit())    {
  192.         static int cvt[] = {SHIFT_INS,END,DN,PGDN,BS,'5',
  193.                         FWD,HOME,UP,PGUP};
  194.         int c = getkey();
  195.  
  196.         /* -------- convert numeric pad keys ------- */
  197.         if (sk & (LEFTSHIFT | RIGHTSHIFT))    {
  198.             if (c >= '0' && c <= '9')
  199.                 c = cvt[c-'0'];
  200.             else if (c == '.' || c == DEL)
  201.                 c = SHIFT_DEL;
  202.             else if (c == INS)
  203.                 c = SHIFT_INS;
  204.         }
  205.         if (c != '\r' && (c < ' ' || c > 127))
  206.             clearBIOSbuffer();
  207.         /* ------ post the keyboard event ------ */
  208.         PostEvent(KEYBOARD, c, sk);
  209.     }
  210.  
  211.     /* ------------ test for mouse events --------- */
  212.     if (button_releases())    {
  213.         /* ------- the button was released -------- */
  214.         doubletimer = DOUBLETICKS;
  215.         PostEvent(BUTTON_RELEASED, mx, my);
  216.         disable_timer(delaytimer);
  217.     }
  218.     get_mouseposition(&mx, &my);
  219.     if (mx != px || my != py)  {
  220.         px = mx;
  221.         py = my;
  222.         PostEvent(MOUSE_MOVED, mx, my);
  223.     }
  224.     if (rightbutton())
  225.         PostEvent(RIGHT_BUTTON, mx, my);
  226.     if (leftbutton())    {
  227.         if (mx == pmx && my == pmy)    {
  228.             /* ---- same position as last left button ---- */
  229.             if (timer_running(doubletimer))    {
  230.                 /* -- second click before double timeout -- */
  231.                 disable_timer(doubletimer);
  232.                 PostEvent(DOUBLE_CLICK, mx, my);
  233.             }
  234.             else if (!timer_running(delaytimer))    {
  235.                 /* ---- button held down a while ---- */
  236.                 delaytimer = lagdelay;
  237.                 lagdelay = DELAYTICKS;
  238.                 /* ---- post a typematic-like button ---- */
  239.                 PostEvent(LEFT_BUTTON, mx, my);
  240.             }
  241.         }
  242.         else    {
  243.             /* --------- new button press ------- */
  244.             disable_timer(doubletimer);
  245.             delaytimer = FIRSTDELAY;
  246.             lagdelay = DELAYTICKS;
  247.             PostEvent(LEFT_BUTTON, mx, my);
  248.             pmx = mx;
  249.             pmy = my;
  250.         }
  251.     }
  252.     else
  253.         lagdelay = FIRSTDELAY;
  254. }
  255.  
  256. /* ----- post a message and parameters to msg queue ---- */
  257. void PostMessage(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  258. {
  259.     if (msg == ENDDIALOG)    {
  260.         msg++;
  261.         --msg;
  262.     }
  263.     if (MsgQueueCtr != MAXMESSAGES)    {
  264.         MsgQueue[MsgQueueOnCtr].wnd = wnd;
  265.         MsgQueue[MsgQueueOnCtr].msg = msg;
  266.         MsgQueue[MsgQueueOnCtr].p1 = p1;
  267.         MsgQueue[MsgQueueOnCtr].p2 = p2;
  268.         if (++MsgQueueOnCtr == MAXMESSAGES)
  269.             MsgQueueOnCtr = 0;
  270.         MsgQueueCtr++;
  271.     }
  272. }
  273.  
  274. /* --------- send a message to a window ----------- */
  275. int SendMessage(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  276. {
  277.     int rtn = TRUE, x, y;
  278.  
  279.     LogMessages(wnd, msg, p1, p2);
  280.     if (wnd != NULL)
  281.         switch (msg)    {
  282.             case PAINT:
  283.             case BORDER:
  284.                 /* ------- don't send these messages unless the
  285.                     window is visible -------- */
  286.                 if (isVisible(wnd))
  287.                     rtn = (*wnd->wndproc)(wnd, msg, p1, p2);
  288.                 break;
  289.             case RIGHT_BUTTON:
  290.             case LEFT_BUTTON:
  291.             case DOUBLE_CLICK:
  292.             case BUTTON_RELEASED:
  293.                 /* --- don't send these messages unless the
  294.                     window is visible or has captured the mouse -- */
  295.                 if (isVisible(wnd) || wnd == CaptureMouse)
  296.                     rtn = (*wnd->wndproc)(wnd, msg, p1, p2);
  297.                 break;
  298.             case KEYBOARD:
  299.             case SHIFT_CHANGED:
  300.                 /* ------- don't send these messages unless the
  301.                     window is visible or has captured the keyboard -- */
  302.                 if (isVisible(wnd) || wnd == CaptureKeyboard)
  303.                     rtn = (*wnd->wndproc)(wnd, msg, p1, p2);
  304.                 break;
  305.             default:
  306.                 rtn = (*wnd->wndproc)(wnd, msg, p1, p2);
  307.                 break;
  308.         }
  309.     /* ----- window processor returned true or the message was sent
  310.         to no window at all (NULL) ----- */
  311.     if (rtn != FALSE)    {
  312.         /* --------- process messages that a window sends to the
  313.             system itself ---------- */
  314.         switch (msg)    {
  315.             case STOP:
  316.                 if (oldtimer != NULL)    {
  317.                     setvect(TIMER, oldtimer);
  318.                     oldtimer = NULL;
  319.                 }
  320.                 if (oldkeyboard != NULL)    {
  321.                     setvect(KEYBOARDVECT, oldkeyboard);
  322.                     oldkeyboard = NULL;
  323.                 }
  324.                 restorevideo();
  325.                 break;
  326.             /* ------- clock messages --------- */
  327.             case CAPTURE_CLOCK:
  328.                 Cwnd = wnd;
  329.                 set_timer(clocktimer, 0);
  330.                 break;
  331.             case RELEASE_CLOCK:
  332.                 Cwnd = NULL;
  333.                 disable_timer(clocktimer);
  334.                 break;
  335.             /* -------- keyboard messages ------- */
  336.             case KEYBOARD_CURSOR:
  337.                 if (wnd == NULL)
  338.                     cursor((int)p1, (int)p2);
  339.                 else if (wnd == inFocus)
  340.                     cursor(GetClientLeft(wnd)+(int)p1,
  341.                                 GetClientTop(wnd)+(int)p2);
  342.                 break;
  343.             case CAPTURE_KEYBOARD:
  344.                 if (p2)
  345.                     ((WINDOW)p2)->PrevKeyboard=CaptureKeyboard;
  346.                 else
  347.                     wnd->PrevKeyboard = CaptureKeyboard;
  348.                 CaptureKeyboard = wnd;
  349.                 NoChildCaptureKeyboard = (int)p1;
  350.                 break;
  351.             case RELEASE_KEYBOARD:
  352.                 if (CaptureKeyboard == wnd || (int)p1)
  353.                     CaptureKeyboard = wnd->PrevKeyboard;
  354.                 else    {
  355.                     WINDOW twnd = CaptureKeyboard;
  356.                     while (twnd != NULL)    {
  357.                         if (twnd->PrevKeyboard == wnd)    {
  358.                             twnd->PrevKeyboard = wnd->PrevKeyboard;
  359.                             break;
  360.                         }
  361.                         twnd = twnd->PrevKeyboard;
  362.                     }
  363.                 }
  364.                 wnd->PrevKeyboard = NULL;
  365.                 NoChildCaptureKeyboard = FALSE;
  366.                 break;
  367.             case CURRENT_KEYBOARD_CURSOR:
  368.                 curr_cursor(&x, &y);
  369.                 *(int*)p1 = x;
  370.                 *(int*)p2 = y;
  371.                 break;
  372.             case SAVE_CURSOR:
  373.                 savecursor();
  374.                 break;
  375.             case RESTORE_CURSOR:
  376.                 restorecursor();
  377.                 break;
  378.             case HIDE_CURSOR:
  379.                 normalcursor();
  380.                 hidecursor();
  381.                 break;
  382.             case SHOW_CURSOR:
  383.                 if (p1)
  384.                     set_cursor_type(0x0106);
  385.                 else
  386.                     set_cursor_type(0x0607);
  387.                 unhidecursor();
  388.                 break;
  389.             case WAITKEYBOARD:
  390.                 waitforkeyboard();
  391.                 break;
  392.             /* -------- mouse messages -------- */
  393.             case RESET_MOUSE:
  394.                 resetmouse();
  395.                 set_mousetravel(0, SCREENWIDTH-1, 0, SCREENHEIGHT-1);
  396.                 break;
  397.             case MOUSE_INSTALLED:
  398.                 rtn = mouse_installed();
  399.                 break;
  400.             case MOUSE_TRAVEL:    {
  401.                 RECT rc = *(RECT *)p1;
  402.                 set_mousetravel(rc.lf, rc.rt, rc.tp, rc.bt);
  403.                 break;
  404.             }
  405.             case SHOW_MOUSE:
  406.                 show_mousecursor();
  407.                 break;
  408.             case HIDE_MOUSE:
  409.                 hide_mousecursor();
  410.                 break;
  411.             case MOUSE_CURSOR:
  412.                 set_mouseposition((int)p1, (int)p2);
  413.                 break;
  414.             case CURRENT_MOUSE_CURSOR:
  415.                 get_mouseposition((int*)p1,(int*)p2);
  416.                 break;
  417.             case WAITMOUSE:
  418.                 waitformouse();
  419.                 break;
  420.             case TESTMOUSE:
  421.                 rtn = mousebuttons();
  422.                 break;
  423.             case CAPTURE_MOUSE:
  424.                 if (p2)
  425.                     ((WINDOW)p2)->PrevMouse = CaptureMouse;
  426.                 else
  427.                     wnd->PrevMouse = CaptureMouse;
  428.                 CaptureMouse = wnd;
  429.                 NoChildCaptureMouse = (int)p1;
  430.                 break;
  431.             case RELEASE_MOUSE:
  432.                 if (CaptureMouse == wnd || (int)p1)
  433.                     CaptureMouse = wnd->PrevMouse;
  434.                 else    {
  435.                     WINDOW twnd = CaptureMouse;
  436.                     while (twnd != NULL)    {
  437.                         if (twnd->PrevMouse == wnd)    {
  438.                             twnd->PrevMouse = wnd->PrevMouse;
  439.                             break;
  440.                         }
  441.                         twnd = twnd->PrevMouse;
  442.                     }
  443.                 }
  444.                 wnd->PrevMouse = NULL;
  445.                 NoChildCaptureMouse = FALSE;
  446.                 break;
  447.             default:
  448.                 break;
  449.         }
  450.     }
  451.     return rtn;
  452. }
  453.  
  454. /* ---- dispatch messages to the message proc function ---- */
  455. int dispatch_message(void)
  456. {
  457.     WINDOW Mwnd, Kwnd;
  458.     /* -------- collect mouse and keyboard events ------- */
  459.     collect_events();
  460.     /* --------- dequeue and process events -------- */
  461.     while (EventQueueCtr > 0)  {
  462.         struct events ev;
  463.             
  464.         ev = EventQueue[EventQueueOffCtr];
  465.         if (++EventQueueOffCtr == MAXMESSAGES)
  466.             EventQueueOffCtr = 0;
  467.         --EventQueueCtr;
  468.  
  469.         /* ------ get the window in which a
  470.                         mouse event occurred ------ */
  471.         Mwnd = inWindow(ev.mx, ev.my);
  472.  
  473.         /* ---- process mouse captures ----- */
  474.         if (CaptureMouse != NULL)
  475.             if (Mwnd == NULL ||
  476.                     NoChildCaptureMouse ||
  477.                         GetParent(Mwnd) != CaptureMouse)
  478.                 Mwnd = CaptureMouse;
  479.  
  480.         /* ------ get the window in which a
  481.                         keyboard event occurred ------ */
  482.         Kwnd = inFocus;
  483.  
  484.         /* ---- process keyboard captures ----- */
  485.         if (CaptureKeyboard != NULL)
  486.             if (Kwnd == NULL ||
  487.                     NoChildCaptureKeyboard ||
  488.                         GetParent(Kwnd) != CaptureKeyboard)
  489.                 Kwnd = CaptureKeyboard;
  490.  
  491.         /* -------- send mouse and keyboard messages to the
  492.             window that should get them -------- */
  493.         switch (ev.event)    {
  494.             case SHIFT_CHANGED:
  495.             case KEYBOARD:
  496.                 SendMessage(Kwnd, ev.event, ev.mx, ev.my);
  497.                 break;
  498.             case LEFT_BUTTON:
  499.                 if (!CaptureMouse ||
  500.                         (!NoChildCaptureMouse &&
  501.                             GetParent(Mwnd) == CaptureMouse))
  502.                     if (Mwnd != inFocus)
  503.                         SendMessage(Mwnd, SETFOCUS, TRUE, 0);
  504.             case BUTTON_RELEASED:
  505.             case DOUBLE_CLICK:
  506.             case RIGHT_BUTTON:
  507.             case MOUSE_MOVED:
  508.                 SendMessage(Mwnd, ev.event, ev.mx, ev.my);
  509.                 break;
  510.             case CLOCKTICK:
  511.                 SendMessage(Cwnd, ev.event,
  512.                     (PARAM) MK_FP(ev.mx, ev.my), 0);
  513.                 break;
  514.             default:
  515.                 break;
  516.         }
  517.     }
  518.     /* ------ dequeue and process messages ----- */
  519.     while (MsgQueueCtr > 0)  {
  520.         struct msgs mq;
  521.  
  522.         mq = MsgQueue[MsgQueueOffCtr];
  523.         if (++MsgQueueOffCtr == MAXMESSAGES)
  524.             MsgQueueOffCtr = 0;
  525.         --MsgQueueCtr;
  526.         SendMessage(mq.wnd, mq.msg, mq.p1, mq.p2);
  527.         if (mq.msg == ENDDIALOG)
  528.             return FALSE;
  529.         if (mq.msg == STOP)    {
  530.             restorecursor();    
  531.             unhidecursor();
  532.             return FALSE;
  533.         }
  534.     }
  535.     return TRUE;
  536. }
  537.  
  538.